
import 'package:basic_common/common_exports.dart';
import 'package:basic_modle/upload_data.dart';
import 'package:dio/dio.dart';
import 'http_data.dart';
import 'http_interceptor.dart';
import 'http_options.dart';
// http 请求单例类
class HttpRequest {
  // 工厂构造方法
 late factory HttpRequest() => _instance;
  // 初始化一个单例实例
  static late final HttpRequest _instance = HttpRequest._internal();
  // dio 实例
   Dio? dio;

  // 内部构造方法
  HttpRequest._internal() {
    // ignore: unnecessary_null_comparison
    if (dio == null) {
      // BaseOptions、Options、RequestOptions 都可以配置参数，优先级别依次递增，且可以根据优先级别覆盖参数
      BaseOptions baseOptions = BaseOptions(
        // baseUrl: HttpOptions.BASE_URL,
        connectTimeout:const Duration(milliseconds:  HttpOptions.CONNECT_TIMEOUT),
        receiveTimeout:const Duration(milliseconds:  HttpOptions.RECEIVE_TIMEOUT), 
        headers: {},
      );
      // 没有实例 则创建之
      dio =  Dio(baseOptions);
      // 添加拦截器
      dio!.interceptors.add(HttpInterceptor());
        //日志记录
      dio!.interceptors.add(LogInterceptor(responseBody: true));
      }
    }
  /// 初始化公共属性 如果需要覆盖原配置项 就调用它
  ///
  /// [baseUrl] 地址前缀
  /// [connectTimeout] 连接超时赶时间
  /// [receiveTimeout] 接收超时赶时间
  /// [headers] 请求头
  /// [interceptors] 基础拦截器
  void init({
    String? baseUrl,
    int? connectTimeout,
    int? receiveTimeout,
    Map<String, dynamic>? headers,
    List<Interceptor>? interceptors,
  }) {
    dio!.options.baseUrl = baseUrl!;
    dio!.options.connectTimeout =Duration(milliseconds: connectTimeout!) ;
    dio!.options.receiveTimeout =Duration(milliseconds: receiveTimeout!) ;
    dio!.options.headers = headers;
    dio!.options.responseType = ResponseType.json;
    if (interceptors != null && interceptors.isNotEmpty) {
      dio!.interceptors.addAll(interceptors);
    }
  }

  /// 设置请求头
  void setHeaders(Map<String, dynamic> headers) {
    dio!.options.headers.addAll(headers);
  }

  final CancelToken _cancelToken =  CancelToken();

  /*
   * 取消请求
   *
   * 同一个cancel token 可以用于多个请求
   * 当一个cancel token取消时，所有使用该cancel token的请求都会被取消。
   * 所以参数可选
   */
  void cancelRequests({CancelToken? token}) {
    token ?? _cancelToken.cancel("cancelled");
  }



  /// restful get 操作
  Future get(
    String? path, {
    Map<String, dynamic>? params,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    Response response = await dio!.get(
      path!,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken ?? _cancelToken,
    );
    return response.data;
  }

  /// restful post 操作
  Future<HttpData> post(
    String path, {
    Map<String, dynamic>? params,
    String? baseUrl,
    dynamic? data,
    Options? options,
    CancelToken? cancelToken,
    bool isshowLoading=false,
    loadingTitle='正在加载...'
  }) async {    
  
     if (isshowLoading) EasyLoading.show(status: loadingTitle);

    dio!.options.baseUrl=baseUrl ?? HttpOptions.BASE_URL;
    Response response = await dio!.post(
      path,
      data: data,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken ?? _cancelToken,
    );
        if (isshowLoading) EasyLoading.dismiss();
    return HttpData.fromJson(response.data) ;
  }
  /// 请求 返回map类型
    Future<dynamic> postMap(
    String path, {
    Map<String, dynamic>? params,
    String? baseUrl,
    dynamic? data,
    Options? options,
    CancelToken? cancelToken,
    bool isshowLoading=false,
    loadingTitle='正在加载...'
  }) async {    
     if (isshowLoading) EasyLoading.show(status: loadingTitle);
    dio!.options.baseUrl=baseUrl??HttpOptions.BASE_URL;
    Response response = await dio!.post(
      path,
      data: data,
      queryParameters: params,
      options: options,
      cancelToken: cancelToken ?? _cancelToken,
    );
        if (isshowLoading) EasyLoading.dismiss();
    return response.data ;
  }

  /// restful post form 表单提交操作
  Future<UploadData> postForm(
    String? path, {
    Map<String, dynamic>? data,
    Map<String, dynamic>? headers,
    Options? options,
    String? baseUrl,
    CancelToken? cancelToken,
     showLoading = false,
      loadTitle = "加载中..."
    
  }) async {
     if (showLoading) EasyLoading.show(status: loadTitle);
    Response response = await dio!.post(
      path!,
      data: FormData.fromMap(data!),
      cancelToken: cancelToken ?? _cancelToken,
    );
     if (showLoading ) EasyLoading.dismiss();
    return UploadData.fromJson(response.data);
  }



  
/// 下载文件
  Future download(
    String url,
    String savePath, {
    Map<String, dynamic>? queryParams,
    CancelToken? cancelToken,
    void Function(int, int)? onReceiveProgress,
  }) async {
    return await dio!.download(
      url,
      savePath,
      queryParameters: queryParams,
      cancelToken: cancelToken,
      onReceiveProgress: onReceiveProgress,
    );
  }


}
